
using System;
using System.Data;
using System.Reflection;

namespace Serpis
{
	public class Persister : IPersister
	{
		/// <summary>
		/// Guarda en la base de datos el objeto indicado.
		/// Para ello busca por reflexión las propiedades decoradas mediante "FieldAttribute" y "PrimaryKeyAttribute"
		/// </summary>
		public virtual void Save(object model)
		{
//			IDbCommand dbCommand = AppDbConnection.Instance.DbConnection.CreateCommand();
//			if (articulo.Id == 0) //insert
//				dbCommand.CommandText = insertCommand;
//			else { //update
//				dbCommand.CommandText = updateCommand;
//				addParameter(dbCommand, "id", articulo.Id);
//			}
//				
//			addParameter(dbCommand, "nombre", articulo.Nombre);
//			addParameter(dbCommand, "precio", articulo.Precio);
//			addParameter(dbCommand, "categoria", articulo.Categoria);
//
//			dbCommand.ExecuteNonQuery();
			
			PersisterInfo persisterInfo = PersisterInfoStore.Get(model.GetType());
			
			IDbCommand dbCommand = AppDbConnection.Instance.DbConnection.CreateCommand();
			
			object id = persisterInfo.PrimaryKey.GetValue(model, null);
			
			if (id == null || id.Equals("") || Convert.ToInt64(id) == 0) //insert
				dbCommand.CommandText = persisterInfo.InsertCommand;
			else {
				dbCommand.CommandText = persisterInfo.UpdateCommand;
				dbCommand.AddParameter(persisterInfo.PrimaryKeyName, id);
			}
			
			int index = 0;
			foreach (PropertyInfo propertyInfo in persisterInfo.Fields) {
				object value = propertyInfo.GetValue(model, null);
				dbCommand.AddParameter(persisterInfo.FieldNames[index] , value);
				index++;
			}
			
			dbCommand.ExecuteNonQuery();
		}

		/// <summary>
		/// Devuelve un nuevo objeto que rellena desde la base de datos.
		/// </summary>
		public virtual object Load(Type type, object id)
		{
//			IDbCommand dbCommand = AppDbConnection.Instance.DbConnection.CreateCommand();
//			dbCommand.CommandText = selectCommand;
//			addParameter(dbCommand, "id", id);
//			
//			IDataReader dataReader = dbCommand.ExecuteReader();
//			dataReader.Read(); //leemos el primer registro (y único)
//			
//			Articulo articulo = new Articulo();
//			articulo.Id = id;
//			articulo.Nombre = (string)dataReader["nombre"];
//			articulo.Precio = (decimal)dataReader["precio"];
//			articulo.Categoria = dataReader["categoria"] is DBNull ? (long?)null : (long)dataReader["categoria"];
//			
//			dataReader.Close();
//			
//			return articulo;
			
			PersisterInfo persisterInfo = PersisterInfoStore.Get(type);
			
			IDbCommand dbCommand = AppDbConnection.Instance.DbConnection.CreateCommand();
			dbCommand.CommandText = persisterInfo.SelectCommand;
			dbCommand.AddParameter(persisterInfo.PrimaryKeyName, id);
			
			IDataReader dataReader = dbCommand.ExecuteReader();
			dataReader.Read();  //leemos el primer registro (y único)
			
			object model = Activator.CreateInstance(type);
			persisterInfo.PrimaryKey.SetValue(model, id, null);
			
			int index = 0;
			foreach (PropertyInfo field in persisterInfo.Fields) {
				string fieldName = persisterInfo.FieldNames[index];
				object value = dataReader[fieldName];
				if (value is DBNull)
					value = null;
				field.SetValue(model, value, null);
				index++;
			}
			
			dataReader.Close();
			
			return model;
		}
		
		public void Delete(Type type, object id)
		{
			PersisterInfo persisterInfo = PersisterInfoStore.Get(type);
			
			IDbCommand dbCommand = AppDbConnection.Instance.DbConnection.CreateCommand();

			dbCommand.CommandText = persisterInfo.DeleteCommand;
			dbCommand.AddParameter(persisterInfo.PrimaryKeyName, id);
			
			dbCommand.ExecuteNonQuery();

		}
	}
}
